import dns.resolver
import socket
import struct
from scapy.all import DNS, DNSQR, IP, Raw

id = 123
qr = 0  # 响应
opcode = 0  # 标准查询
aa = 0  # 不是权威应答
tc = 0  # 没有截断
rd = 1  # 递归查询
ra = 0  # 没有回应者
z = 0  # 保留字段
rcode = 0  # 无错误
qdcount = 1  # 一个问题
ancount = 0  # 没有回答
nscount = 0  # 没有授权记录
arcount = 0  # 没有附加记录
qname = 'bilibili.com'
qtype = 1  # A记录
qclass = 1  # 互联网

def dns_question() :
    # 将应答标志、操作码、权威回答、递归查询、期望适应者、回应者标志移位，然后合并为一个字节
    flags = (qr << 15) | (opcode << 11) | (aa << 10) | (tc << 9) | (rd << 8) | (ra << 7) | (z << 4) | rcode
 
    # 将问题数、回答数、授权记录数、附加记录数转换为网络字节序
    # qdcount_network, ancount_network, nscount_network, arcount_network = map(lambda x: x.to_bytes(2, 'big'), [qdcount, ancount, nscount, arcount])
    qdcount_network, ancount_network, nscount_network, arcount_network = qdcount, ancount, nscount, arcount
 
    # 将域名转换为标签格式
    qname_labels = qname.split('.')
    qname_encoded = b''
    for label in qname_labels:
        qname_encoded += bytes([len(label)]) + label.encode()
    qname_encoded += b'\0'
 
    # 将查询类型和类转换为网络字节序
    # qtype_network, qclass_network = map(lambda x: x.to_bytes(2, 'big'), [qtype, qclass])
    qtype_network, qclass_network = qtype, qclass
 

    # 组合DNS头部和问题部分
    dns_header = struct.pack('>HHHHHH', id, flags, qdcount_network, ancount_network, nscount_network, arcount_network)
    dns_question = qname_encoded + struct.pack('>HH', qtype_network, qclass_network)
 
    return dns_header + dns_question

def truth_data():
    answers = dns.resolver.query(qname, qtype)
 
    # 打印查询结果
    for record in answers:
        print(record.to_text())

if __name__=="__main__":
    dns_question_packet = dns_question()
    question_len = len(dns_question_packet)

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 连接到服务器 (替换为实际的IP地址和端口)
    s.connect(('8.8.8.8', 53))
    # 发送数据
    # print(dns_question_packet)
    s.sendall(dns_question_packet)
    msg = s.recv(1024)
    print(len(msg))

    unpacked_value = struct.unpack('>'+'b'*len(msg), msg)
    # print(str(unpacked_value))
    print(unpacked_value)

    buf_len = len(msg)

    rest_answer_data = msg[question_len:]
    rest_len = buf_len - question_len
    assert rest_len%16==0
    while rest_len>0:
        print(rest_answer_data[12],rest_answer_data[13],rest_answer_data[14],rest_answer_data[15] )
        rest_answer_data = rest_answer_data[16:]
        rest_len-=16

    truth_data()
